/*     */ package com.zimbra.cs.imap;
/*     */ 
/*     */ import com.zimbra.common.account.Key.AccountBy;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.mailbox.MailItem;
/*     */ import com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.cs.mime.Mime.FixedMimeMessage;
/*     */ import com.zimbra.cs.service.AuthProvider;
/*     */ import com.zimbra.cs.service.UserServlet;
/*     */ import com.zimbra.cs.service.UserServlet.HttpInputStream;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import com.zimbra.cs.util.JMSession;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.PrintStream;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.net.URLDecoder;
/*     */ import java.net.URLEncoder;
/*     */ import java.util.HashMap;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ 
/*     */ 
/*     */ final class ImapURL
/*     */ {
/*     */   private String mURL;
/*     */   private String mUsername;
/*     */   private String mHostname;
/*     */   private short mPort;
/*     */   private ImapPath mPath;
/*     */   private int mUid;
/*     */   private ImapPartSpecifier mPart;
/*     */   
/*     */   private static class ImapUrlException
/*     */     extends ImapParseException
/*     */   {
/*     */     private static final long serialVersionUID = 174398702563521440L;
/*     */     
/*     */     ImapUrlException(String tag, String url, String message)
/*     */     {
/*  52 */       super("BADURL \"" + url.replace("\\", "\\\\").replace("\"", "\\\"") + '"', "APPEND failed: " + message, false);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   ImapURL(String tag, ImapHandler handler, String url)
/*     */     throws ImapParseException
/*     */   {
/*  68 */     if ((url == null) || (url.length() == 0))
/*  69 */       throw new ImapUrlException(tag, url, "blank/null IMAP URL");
/*  70 */     parse(tag, handler.getCredentials(), url);
/*  71 */     this.mURL = url;
/*     */     
/*  73 */     if ((this.mPath == null) || (this.mPath.asZimbraPath().length() == 0)) {
/*  74 */       if (handler.getState() != ImapHandler.State.SELECTED)
/*  75 */         throw new ImapUrlException(tag, url, "IMAP URL must specify folder if session not SELECTED");
/*  76 */       this.mPath = handler.getCurrentSession().getPath();
/*     */     }
/*     */     
/*  79 */     if ((this.mUsername == null) || (this.mUsername.length() == 0)) {
/*  80 */       if (handler.getState() == ImapHandler.State.NOT_AUTHENTICATED)
/*  81 */         throw new ImapUrlException(tag, url, "IMAP URL must specify user if session not AUTHENTICATED");
/*  82 */       this.mUsername = handler.getCredentials().getUsername();
/*  83 */       if ((this.mPath != null) && (this.mPath.getOwner() != null)) {
/*     */         try {
/*  85 */           Account owner = this.mPath.getOwnerAccount();
/*  86 */           if (owner != null)
/*  87 */             this.mUsername = owner.getName();
/*     */         } catch (ServiceException e) {
/*  89 */           throw new ImapUrlException(tag, url, "could not look up user: " + this.mPath.getOwner());
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*  94 */     if ((this.mHostname == null) || (this.mHostname.length() == 0)) {
/*     */       try {
/*  96 */         Account acct = Provisioning.getInstance().get(Key.AccountBy.name, this.mUsername);
/*  97 */         if (acct == null)
/*  98 */           throw new ImapUrlException(tag, url, "unknown user: " + this.mUsername);
/*  99 */         this.mHostname = acct.getMailHost();
/*     */       } catch (ServiceException e) {
/* 101 */         throw new ImapUrlException(tag, url, "could not look up user: " + this.mUsername);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   String getURL() {
/* 107 */     return this.mURL;
/*     */   }
/*     */   
/*     */   private void parse(String tag, ImapCredentials creds, String url) throws ImapParseException {
/* 111 */     String lcurl = url.toLowerCase();
/* 112 */     int pos = 0;
/*     */     
/*     */ 
/* 115 */     if ((url.length() > 7) && (lcurl.startsWith("imap://")))
/*     */     {
/* 117 */       pos += 7;
/* 118 */       int slash = url.indexOf('/', pos);int ampersand = url.indexOf('@', pos);
/* 119 */       if ((slash == -1) || (slash == pos)) {
/* 120 */         throw new ImapUrlException(tag, url, "malformed IMAP URL");
/*     */       }
/* 122 */       if ((ampersand != -1) && (ampersand < slash))
/*     */       {
/*     */ 
/* 125 */         int semicolon = url.indexOf(';', pos);
/* 126 */         this.mUsername = urlDecode(url.substring(pos, (semicolon != -1) && (semicolon < ampersand) ? semicolon : ampersand));
/*     */         
/* 128 */         pos = ampersand + 1;
/*     */       }
/*     */       
/* 131 */       int colon = url.indexOf(':', pos);
/* 132 */       if ((colon != -1) && (colon < slash)) {
/*     */         try {
/* 134 */           this.mPort = Short.parseShort(url.substring(colon + 1, slash));
/*     */         } catch (NumberFormatException nfe) {
/* 136 */           throw new ImapUrlException(tag, url, "invalid port: " + url.substring(colon + 1, slash));
/*     */         }
/*     */       }
/* 139 */       this.mHostname = url.substring(pos, (colon != -1) && (colon < slash) ? colon : slash);
/* 140 */       pos = slash + 1;
/*     */     }
/* 142 */     else if (url.charAt(0) != '/') {
/* 143 */       throw new ImapUrlException(tag, url, "relative IMAP URLs must begin with '/'");
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 152 */     int iuid = lcurl.indexOf("/;uid=", pos);int uvv = lcurl.indexOf(";uidvalidity=", pos);
/* 153 */     if (iuid == -1) {
/* 154 */       throw new ImapUrlException(tag, url, "only \"imessagepart\"-type IMAP URLs supported");
/*     */     }
/* 156 */     this.mPath = new ImapPath(urlDecode(url.substring(pos, (uvv != -1) && (uvv < iuid) ? uvv : iuid)), creds);
/* 157 */     pos = iuid + 6;
/*     */     
/* 159 */     int isection = lcurl.indexOf("/;section=", pos);
/* 160 */     String uid = url.substring(pos, isection != -1 ? isection : url.length());
/*     */     try {
/* 162 */       this.mUid = Integer.parseInt(uid);
/* 163 */     } catch (NumberFormatException nfe) { throw new ImapUrlException(tag, url, "invalid uid in IMAP URL: " + uid);
/*     */     }
/* 165 */     if (isection != -1) {
/* 166 */       String section = urlDecode(url.substring(isection + 10));
/* 167 */       if (section.length() > 0) {
/*     */         try {
/* 169 */           ImapRequest req = new ParserImapRequest(tag, section);
/* 170 */           this.mPart = req.readPartSpecifier(false, false);
/* 171 */           if (!req.eof()) {
/* 172 */             throw new ImapUrlException(tag, url, "extra chars at end of IMAP URL SECTION");
/*     */           }
/*     */         } catch (ImapParseException ipe) {
/* 175 */           throw new ImapUrlException(tag, url, ipe.getMessage());
/*     */         } catch (IOException ioe) {
/* 177 */           throw new ImapUrlException(tag, url, ioe.getMessage());
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private static class ParserImapRequest extends ImapRequest
/*     */   {
/*     */     public ParserImapRequest(String tag, String section) {
/* 186 */       super();
/* 187 */       this.tag = tag;
/* 188 */       addPart(section);
/*     */     }
/*     */     
/*     */     private Literal getNextBuffer() throws ImapParseException {
/* 192 */       if (this.index + 1 >= this.parts.size()) {
/* 193 */         throw new ImapParseException(this.tag, "no next literal");
/*     */       }
/* 195 */       Literal literal = ((ImapRequest.Part)this.parts.get(this.index + 1)).getLiteral();
/* 196 */       this.index += 2;
/* 197 */       this.offset = 0;
/* 198 */       return literal;
/*     */     }
/*     */     
/*     */     Literal readLiteral() throws ImapParseException
/*     */     {
/* 203 */       return getNextBuffer();
/*     */     }
/*     */   }
/*     */   
/*     */   private String urlDecode(String raw) {
/*     */     try {
/* 209 */       return URLDecoder.decode(raw, "utf-8");
/*     */     } catch (UnsupportedEncodingException uee) {}
/* 211 */     return raw;
/*     */   }
/*     */   
/*     */   public byte[] getContent(ImapHandler handler, ImapCredentials creds, String tag) throws ImapException
/*     */   {
/* 216 */     Pair<Long, InputStream> content = getContentAsStream(handler, creds, tag);
/*     */     try {
/* 218 */       return ByteUtil.getContent((InputStream)content.getSecond(), (int)Math.min(((Long)content.getFirst()).longValue(), 2147483647L));
/*     */     } catch (IOException e) {
/* 220 */       ZimbraLog.imap.info("error reading content from IMAP URL", e);
/*     */       
/* 222 */       throw new ImapUrlException(tag, this.mURL, "error fetching IMAP URL content");
/*     */     }
/*     */   }
/*     */   
/*     */   public Pair<Long, InputStream> getContentAsStream(ImapHandler handler, ImapCredentials creds, String tag) throws ImapException {
/* 227 */     ImapHandler.State state = handler.getState();
/* 228 */     if (state == ImapHandler.State.NOT_AUTHENTICATED) {
/* 229 */       throw new ImapUrlException(tag, this.mURL, "must be in AUTHENTICATED state");
/*     */     }
/*     */     try {
/* 232 */       Account acct = Provisioning.getInstance().get(Key.AccountBy.name, this.mUsername);
/* 233 */       if (acct == null) {
/* 234 */         throw new ImapUrlException(tag, this.mURL, "cannot find user: " + this.mUsername);
/*     */       }
/* 236 */       ImapSession i4session = handler.getCurrentSession();
/* 237 */       OperationContext octxt = creds.getContext().setSession(i4session);
/* 238 */       Pair<Long, InputStream> content = null;
/*     */       
/* 240 */       ImapFolder i4folder = handler.getSelectedFolder();
/* 241 */       if ((state == ImapHandler.State.SELECTED) && (i4session != null) && (i4folder != null) && 
/* 242 */         (acct.getId().equals(i4session.getTargetAccountId())) && (this.mPath.isEquivalent(i4folder.getPath()))) {
/* 243 */         ImapMessage i4msg = i4folder.getByImapId(this.mUid);
/* 244 */         if ((i4msg == null) || (i4msg.isExpunged())) {
/* 245 */           throw new ImapUrlException(tag, this.mURL, "no such message");
/*     */         }
/* 247 */         MailItem item = i4folder.getMailbox().getItemById(octxt, i4msg.msgId, i4msg.getType());
/* 248 */         content = ImapMessage.getContent(item);
/*     */       }
/*     */       
/*     */ 
/* 252 */       if ((content == null) && (this.mPath.onLocalServer())) {
/* 253 */         Mailbox mbox = (Mailbox)this.mPath.getOwnerMailbox();
/* 254 */         MailItem item = mbox.getItemByImapId(octxt, this.mUid, this.mPath.asItemId().getId());
/* 255 */         if (!ImapMessage.SUPPORTED_TYPES.contains(item.getType())) {
/* 256 */           throw new ImapUrlException(tag, this.mURL, "no such message");
/*     */         }
/* 258 */         content = ImapMessage.getContent(item);
/*     */       }
/*     */       
/* 261 */       if (content == null) {
/* 262 */         Account authacct = Provisioning.getInstance().get(Key.AccountBy.id, creds.getAccountId());
/* 263 */         AuthToken auth = AuthProvider.getAuthToken(authacct, System.currentTimeMillis() + 60000L);
/* 264 */         HashMap<String, String> params = new HashMap();
/* 265 */         params.put("imap_id", Integer.toString(this.mUid));
/* 266 */         UserServlet.HttpInputStream is = UserServlet.getRemoteContentAsStream(auth, acct, this.mPath.asResolvedPath(), params);
/* 267 */         content = new Pair(Long.valueOf(is.getContentLength()), is);
/*     */       }
/*     */       
/*     */ 
/* 271 */       if (this.mPart == null) {
/* 272 */         return content;
/*     */       }
/*     */       MimeMessage mm;
/*     */       try
/*     */       {
/* 277 */         mm = new Mime.FixedMimeMessage(JMSession.getSession(), (InputStream)content.getSecond());
/*     */       } finally {
/* 279 */         ((InputStream)content.getSecond()).close();
/*     */       }
/* 281 */       Pair<Long, InputStream> part = this.mPart.getContent(mm);
/* 282 */       if (part == null) {
/* 283 */         throw new ImapUrlException(tag, this.mURL, "no such part");
/*     */       }
/* 285 */       return part;
/*     */     }
/*     */     catch (MailServiceException.NoSuchItemException e) {
/* 288 */       ZimbraLog.imap.info("no such message", e);
/*     */     } catch (ServiceException e) {
/* 290 */       ZimbraLog.imap.info("can't fetch content from IMAP URL", e);
/*     */     } catch (MessagingException e) {
/* 292 */       ZimbraLog.imap.info("can't fetch content from IMAP URL", e);
/*     */     } catch (IOException e) {
/* 294 */       ZimbraLog.imap.info("error reading content from IMAP URL", e);
/*     */     } catch (ImapPartSpecifier.BinaryDecodingException e) {
/* 296 */       ZimbraLog.imap.info("can't fetch content from IMAP URL", e);
/*     */     }
/* 298 */     throw new ImapUrlException(tag, this.mURL, "error fetching IMAP URL content");
/*     */   }
/*     */   
/*     */   public String toString()
/*     */   {
/*     */     try {
/* 304 */       return "imap://" + URLEncoder.encode(this.mUsername, "utf-8") + '@' + this.mHostname + (this.mPort > 0 ? ":" + this.mPort : "") + '/' + URLEncoder.encode(this.mPath.asImapPath(), "utf-8") + "/;UID=" + this.mUid + (this.mPart != null ? "/;SECTION=" + URLEncoder.encode(this.mPart.getSectionSpec(), "utf-8") : "");
/*     */     }
/*     */     catch (UnsupportedEncodingException e)
/*     */     {
/* 308 */       return "imap://" + this.mUsername + '@' + this.mHostname + (this.mPort > 0 ? ":" + this.mPort : "") + '/' + this.mPath + "/;UID=" + this.mUid + (this.mPart != null ? "/;SECTION=" + this.mPart.getSectionSpec() : "");
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public int hashCode()
/*     */   {
/* 315 */     int prime = 31;
/* 316 */     int result = 1;
/* 317 */     result = 31 * result + (this.mHostname == null ? 0 : this.mHostname.hashCode());
/* 318 */     result = 31 * result + (this.mPart == null ? 0 : this.mPart.hashCode());
/* 319 */     result = 31 * result + (this.mPath == null ? 0 : this.mPath.hashCode());
/* 320 */     result = 31 * result + this.mPort;
/* 321 */     result = 31 * result + (this.mURL == null ? 0 : this.mURL.hashCode());
/* 322 */     result = 31 * result + this.mUid;
/* 323 */     result = 31 * result + (this.mUsername == null ? 0 : this.mUsername.hashCode());
/* 324 */     return result;
/*     */   }
/*     */   
/*     */   public boolean equals(Object obj)
/*     */   {
/* 329 */     if (this == obj) {
/* 330 */       return true;
/*     */     }
/* 332 */     if (obj == null) {
/* 333 */       return false;
/*     */     }
/* 335 */     if (getClass() != obj.getClass()) {
/* 336 */       return false;
/*     */     }
/* 338 */     ImapURL other = (ImapURL)obj;
/* 339 */     if (this.mHostname == null) {
/* 340 */       if (other.mHostname != null) {
/* 341 */         return false;
/*     */       }
/* 343 */     } else if (!this.mHostname.equals(other.mHostname)) {
/* 344 */       return false;
/*     */     }
/* 346 */     if (this.mPart == null) {
/* 347 */       if (other.mPart != null) {
/* 348 */         return false;
/*     */       }
/* 350 */     } else if (!this.mPart.equals(other.mPart)) {
/* 351 */       return false;
/*     */     }
/* 353 */     if (this.mPath == null) {
/* 354 */       if (other.mPath != null) {
/* 355 */         return false;
/*     */       }
/* 357 */     } else if (!this.mPath.equals(other.mPath)) {
/* 358 */       return false;
/*     */     }
/* 360 */     if (this.mPort != other.mPort) {
/* 361 */       return false;
/*     */     }
/* 363 */     if (this.mURL == null) {
/* 364 */       if (other.mURL != null) {
/* 365 */         return false;
/*     */       }
/* 367 */     } else if (!this.mURL.equals(other.mURL)) {
/* 368 */       return false;
/*     */     }
/* 370 */     if (this.mUid != other.mUid) {
/* 371 */       return false;
/*     */     }
/* 373 */     if (this.mUsername == null) {
/* 374 */       if (other.mUsername != null) {
/* 375 */         return false;
/*     */       }
/* 377 */     } else if (!this.mUsername.equals(other.mUsername)) {
/* 378 */       return false;
/*     */     }
/* 380 */     return true;
/*     */   }
/*     */   
/*     */   public static void main(String[] args) throws ImapParseException, ServiceException, IOException {
/* 384 */     Account acct = Provisioning.getInstance().get(Key.AccountBy.name, "user1@macbeth.liquidsys.com");
/* 385 */     ImapCredentials creds = new ImapCredentials(acct, ImapCredentials.EnabledHack.NONE);
/* 386 */     ImapHandler handler = new TcpImapHandler(null).setCredentials(creds);
/* 387 */     handler.setSelectedFolder(new ImapPath("trash", creds), (byte)0);
/*     */     
/* 389 */     System.out.println(new ImapURL("tag", handler, "/Drafts;UIDVALIDITY=385759045/;UID=20/;section=HEADER"));
/* 390 */     System.out.println(new ImapURL("tag", handler, "/;UID=20/;section=1.mime"));
/* 391 */     System.out.println(new ImapURL("tag", handler, "/INBOX;UIDVALIDITY=785799047/;UID=113330/;section=1.5.9"));
/* 392 */     System.out.println(new ImapURL("tag", handler, "imap://minbari.org:7143/\\\"gray-council\\\";UIDVALIDITY=385759045/;UID=20"));
/* 393 */     System.out.println(new ImapURL("tag", handler, "imap://bester;auth=gssapi@psicorp.org/~peter/%E6%97%A5%E6%9C%AC%E8%AA%9E/%E5%8F%B0%E5%8C%97/;UID=11916"));
/* 394 */     System.out.println(new ImapURL("tag", handler, "imap://;AUTH=*@minbari.org/gray-council/;uid=20/;section="));
/*     */     
/* 396 */     System.out.println(new ImapUrlException("tag", "\"\\\"", "msg").mCode);
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/ImapURL.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */